package config

import (
	"github.com/stretchr/testify/assert/yaml"
	"os"
	"reflect"
	"strconv"
)

type Config struct {
	Name      string           `yaml:"name"`
	PrjHome   string           `yaml:"prj_home"`
	Http      http             `yaml:"http"`
	Log       Log              `yaml:"log"`
	Db        map[string]db    `yaml:"db"`
	ServerLog ServiceLog       `yaml:"server_log"`
	Redis     map[string]Redis `yaml:"redis"`
}

func NewConfig() *Config {
	return &Config{}
}

func (c *Config) ParseConfig(path string) error {
	//读取问卷
	data, err := os.ReadFile(path)
	if err != nil {
		return err
	}
	return yaml.Unmarshal(data, c)
}

func (c *Config) MergeEnv() {
	assign(reflect.ValueOf(c))
}

func assign(val reflect.Value) {
	//如果传入的值为指针时，将指针还原为普通变量
	v := reflect.Indirect(val)

	//便利结构体
	for i := 0; i < v.NumField(); i++ {
		key := v.Type().Field(i).Tag.Get("env")
		processOne(v.Field(i), key)
	}
}

func processOne(field reflect.Value, key string) {
	envVal, ok := os.LookupEnv(key)

	switch field.Type().Kind() {
	case reflect.String:
		if !ok {
			return
		}
		field.SetString(envVal)
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		if !ok {
			return
		}
		intV, err := strconv.ParseInt(envVal, 0, field.Type().Bits())
		if err != nil {
			return
		}
		field.SetInt(intV)
	case reflect.Float64, reflect.Float32:
		if !ok {
			return
		}
		floatV, err := strconv.ParseFloat(envVal, field.Type().Bits())
		if err != nil {
			return
		}
		field.SetFloat(floatV)
	case reflect.Bool:
		if !ok {
			return
		}
		boolV, err := strconv.ParseBool(envVal)
		if err != nil {
			return
		}
		field.SetBool(boolV)
	case reflect.Struct:
		assign(field)
	}
}
